import os
from helpers import checkexists, DirStack
import commands


def is_git_repository():
    status, out = commands.getstatusoutput('git branch')
    return status == 0

VERSION_FILE_NAME = 'LAST_REVISION'

class GitVersion(object):
    root_dir = os.path.realpath(os.path.dirname(__file__))

    def last_version_file_name(self):
       return os.path.join(self.root_dir, VERSION_FILE_NAME)

    def last_builded(self):
        name = self.last_version_file_name()
        commit = ''
        if os.path.exists(name):
            commit = open(name, 'r').readline()
        return commit

    def all_commits(self):
        return os.popen('git log --pretty=format:"%H [%an] %s"').read().strip().split('\n')

    def all_commits_num(self):
        return len(self.all_commits())

    def actual_changes_list(self):
        """
        returns changes from last git commit till now.
        list sorted in descent order.
        """
        last_commit = self.last_builded()
        changes = []
        for ch in self.all_commits():
            commit, descr = ch.split(' ', 1)
            if commit.strip() == last_commit.strip():
                break
            else:
                changes.append(descr)
        return changes


def get_svn_revisions(build_info):
    """
    Return last build revision from LAST_REVISION file and
    current revision from
    """
    last_build_revision = load_last_revision(build_info)
    current_revision = get_svn_revision(build_info.sources_dir)
    return last_build_revision, current_revision

# backward compatibility
def get_revisions(build_info):
    if is_git_repository():
        version = GitVersion()
        return version.last_builded(), version.all_commits_num()
    else:
        return get_svn_revisions(build_info)
    

def get_changelog_core(rev_from, rev_to):
    if is_git_repository():
        version = GitVersion()
        changes = ['  * %s' % c for c in version.actual_changes_list()]
        return '\n'.join(changes)
    else:
        return get_svn_changelog_core(rev_from, rev_to)


def get_svn_revision(dir_to_checkout):
    """
    Call 'svn' for dir_to_checkout and parse revision from output
    """
    if is_git_repository():
        version = GitVersion()
        return version.all_commits_num() 
    ds = DirStack()
    ds.pushd(dir_to_checkout)
    os.popen('svn up').read()
    svn_out = os.popen('svn info').read()
    ds.popd()

    if svn_out == '':
        raise Exception, 'Cannot get revision from svn'

    try:
        svn_params = dict(line.strip().split(': ', 1)
            for line in svn_out.split('\n') if ': ' in line)
        return int(svn_params.get('Revision', svn_params.get('\xd0\xa0\xd0\xb5\xd0\xb4\xd0\xb0\xd0\xba\xd1\x86\xd0\xb8\xd1\x8f')))
    except Exception, e:
        raise Exception('Cannot parse revision: %s' % e)

def get_svn_changelog_core(rev_from, rev_to):
    """
    Return *-formatted items from svn log _without_ header/footer. E.g.:
    =============
      * feature
      * feature
      * bug
      * bug
    =============
    """
    svn_out = os.popen('svn log -r%d:%d' % (rev_from, rev_to)).read()
    lines = [s.strip(' -') for s in svn_out.split('\n')]
    return '\n'.join('  * %s' % line for line in lines
         if not line == '' and
            not line.startswith('-----') and
            not (line[0] == 'r' and (line.endswith(' lines') or line.endswith(' line'))))


def load_last_revision(build):
    """
    Get last revision value from LAST_REVISION file
    """
    last_revision_file = os.path.join(build.build_dir, VERSION_FILE_NAME)
    if os.path.exists(last_revision_file):
        data = open(last_revision_file, 'r').read()
    else:
        data = ''
    return data and int(data) or 1

def save_last_revision(build, revision):
    """
    Save revision value to VERSION_FILE_NAME file
    """
    last_revision_file = os.path.join(build.build_dir, VERSION_FILE_NAME)
    f = open(last_revision_file, 'w')
    f.write(str(revision))
    f.close()
